package com.hejing.线程安全问题;

import java.util.concurrent.locks.ReentrantLock;

/**
 * ClassName: WindowTest
 * Package: com.hejing.线程安全问题
 * Description:
 *      使用实现Runnable的方式，实现卖票
 * @Author: HeJing
 * @Create: 2023-04-14 19:21
 * @Version: 1.0
 */
public class LockTest {
    public static void main(String[] args) {

        SaleTicketWithLock s1 = new SaleTicketWithLock();
        Thread t1 = new Thread(s1);
        Thread t2 = new Thread(s1);
        Thread t3 = new Thread(s1);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

class SaleTicketWithLock implements Runnable {
    int ticket = 100;

    // lOCK方式解决线程安全问题
    // 步骤1: 创建lock 的实例
    // 注意，需要确保多个线程共用一个 lock实例，因此可以将之声明为 static final 形式(实际上在runnable 线程格式中可以不用)
    private static final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while(true) {
            try {
                // 步骤2: 执行lock.lock()方法，锁定对共享资源的调用
                lock.lock();
                if(ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "售票, 票号为: " + (101 - ticket));
                    ticket--;
                } else {
                    break;
                }
            } finally {
                // 步骤3: 调用lock.unlock(): 释放对共享数据的锁定，为了保证该方法一定会被执行，将之放置在 finally中。
                lock.unlock();  // 为了保证 lock.unlock()方法一定会被执行，考虑将lock.unlock()放置到 finally代码块中
            }
        }
    }
}
























